/*************************************************
 * IAP 升级程序的 APP
 *
 * CPU:     STM32F103C8
 *
 * ************************************************
*/

#include <stdio.h>
#include <string.h>
#include "stm32f10x.h"
#include "systick.h"
#include "led.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"

static void _Usart1GpioConfig(void);

void Test1Task(void *pvParameters);
void Test2Task(void *pvParameters);
void Test3Task(void *pvParameters);

UsartType_t usart1 = { 0 };

int main()
{
    /* 关中断 */
    __disable_irq();

    /* 设置中断向量表偏移地址 */
    extern int __Vectors;
    SCB->VTOR = (uint32_t)&__Vectors;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    Systick_Init();

    LED_Init();

    Usart_Constructor(&usart1, USART1, 128);
    UsartContig_t usart1_config = {
        .baudrate   = 115200,
        .databits   = USART_WordLength_8b,
        .parity     = USART_Parity_No,
        .stopbits   = USART_StopBits_1,
        .GpioConfig = _Usart1GpioConfig
    };
    Usart_Init(&usart1, &usart1_config);
    USART_IdleDmaInit(&usart1);

    BaseType_t rslt = pdFALSE;
    rslt = xTaskCreate(Test1Task, "Test1Task", 128, NULL, 1, NULL);
    if(pdPASS != rslt)
    {
        printf("Create Test1Task failed!\r\n");
    }
    else
    {
        printf("Create Test1Task success!\r\n");
    }
    rslt = xTaskCreate(Test2Task, "Test2Task", 128, NULL, 1, NULL);
    if(pdPASS != rslt)
    {
        printf("Create Test2Task failed!\r\n");
    }
    else
    {
        printf("Create Test2Task success!\r\n");
    }
    rslt = xTaskCreate(Test3Task, "Test3Task", 128, NULL, 1, NULL);
    if(pdPASS != rslt)
    {
        printf("Create Test3Task failed!\r\n");
    }
    else
    {
        printf("Create Test3Task success!\r\n");
    }

    LED_On(0);
    vTaskStartScheduler();

    // Test1Task(NULL);

    while (1)
    {
    }
}

void Test1Task(void *pvParameters)
{
    uint32_t tick = Systick_GetTick();
    while(1)
    {
        uint8_t data[128] = { 0 };
        int len = USART_ReadFromDma(&usart1, data);
        if(len > 0)
        {
            USART_Send(&usart1, data, len, 50);
        }

        if(Systick_GetTickDiff(tick) > 1000)
        {
            printf("app1\r\n");
            tick = Systick_GetTick();
        }
    }
}

void Test2Task(void *pvParameters)
{
    while(1)
    {
        printf("app2\r\n");
        vTaskDelay(1000);
    }
}

void Test3Task(void *pvParameters)
{
    uint8_t led = 0;
    while(1)
    {
        LED_On(led);
        led = !led;
        vTaskDelay(1000);
    }
}

static void _Usart1GpioConfig(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure = {
        .GPIO_Pin   = GPIO_Pin_9,
        .GPIO_Mode  = GPIO_Mode_AF_PP,
        .GPIO_Speed = GPIO_Speed_50MHz
    };
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

int fputc(int ch, FILE *f)
{
    USART_SendData(USART1, (uint8_t)ch);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    return ch;
}
